home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TeX 1995 July
/
TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO
/
graphics
/
tiff
/
tools
/
tiffcp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-03-26
|
15KB
|
551 lines
#ifndef lint
static char rcsid[] = "$Header: /usr/people/sam/tiff/tools/RCS/tiffcp.c,v 1.19 92/03/27 12:11:24 sam Exp $";
#endif
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler
* Copyright (c) 1991, 1992 Silicon Graphics, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee, provided
* that (i) the above copyright notices and this permission notice appear in
* all copies of the software and related documentation, and (ii) the names of
* Sam Leffler and Silicon Graphics may not be used in any advertising or
* publicity relating to the software without the specific, prior written
* permission of Sam Leffler and Silicon Graphics.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#include <stdio.h>
#include "tiffio.h"
typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned int u_int;
typedef unsigned long u_long;
#if defined(VMS)
#define unlink delete
#endif
#define streq(a,b) (strcmp(a,b) == 0)
#define CopyField(tag, v) \
if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
#define CopyField2(tag, v1, v2) \
if (TIFFGetField(in, tag, &v1, &v2)) TIFFSetField(out, tag, v1, v2)
#define CopyField3(tag, v1, v2, v3) \
if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3)
#define CopyField4(tag, v1, v2, v3, v4) \
if (TIFFGetField(in, tag, &v1, &v2, &v3, &v4)) TIFFSetField(out, tag, v1, v2, v3, v4)
static short config;
static u_short compression;
static u_short predictor;
static u_short fillorder;
static long rowsperstrip;
static long g3opts;
static int ignore = 0; /* if true, ignore read errors */
static char *filename;
static int tiffcp();
static int cpContig2ContigByRow();
static int cpContig2SeparateByRow();
static int cpSeparate2ContigByRow();
static int cpSeparate2SeparateByRow();
static int cpDecodedStrips();
static void usage();
main(argc, argv)
char *argv[];
{
short defconfig = -1;
u_short defcompression = -1;
u_short defpredictor = 0;
u_short deffillorder = 0;
long defrowsperstrip = -1;
long defg3opts = 0;
TIFF *in, *out;
argc--, argv++;
if (argc < 2)
usage();
for (; argc > 2 && argv[0][0] == '-'; argc--, argv++) {
if (streq(argv[0], "-none")) {
defcompression = COMPRESSION_NONE;
continue;
}
if (streq(argv[0], "-packbits")) {
defcompression = COMPRESSION_PACKBITS;
continue;
}
if (streq(argv[0], "-lzw")) {
defcompression = COMPRESSION_LZW;
continue;
}
if (streq(argv[0], "-g3")) {
defcompression = COMPRESSION_CCITTFAX3;
continue;
}
if (streq(argv[0], "-g4")) {
defcompression = COMPRESSION_CCITTFAX4;
continue;
}
if (streq(argv[0], "-contig")) {
defconfig = PLANARCONFIG_CONTIG;
continue;
}
if (streq(argv[0], "-separate")) {
defconfig = PLANARCONFIG_SEPARATE;
continue;
}
if (streq(argv[0], "-lsb2msb")) {
deffillorder = FILLORDER_LSB2MSB;
continue;
}
if (streq(argv[0], "-msb2lsb")) {
deffillorder = FILLORDER_MSB2LSB;
continue;
}
if (streq(argv[0], "-rowsperstrip")) {
argc--, argv++;
defrowsperstrip = atoi(argv[0]);
continue;
}
if (streq(argv[0], "-2d")) {
defg3opts = GROUP3OPT_2DENCODING;
continue;
}
if (streq(argv[0], "-fill")) {
defg3opts |= GROUP3OPT_FILLBITS;
continue;
}
if (streq(argv[0], "-predictor")) {
argc--, argv++;
defpredictor = atoi(argv[0]);
continue;
}
if (streq(argv[0], "-ignore")) {
ignore = 1;
continue;
}
usage();
}
out = TIFFOpen(argv[argc-1], "w");
if (out == NULL)
exit(-2);
for (; argc > 1; argc--, argv++) {
in = TIFFOpen(filename = argv[0], "r");
if (in != NULL) {
do {
config = defconfig;
compression = defcompression;
predictor = defpredictor;
fillorder = deffillorder;
rowsperstrip = defrowsperstrip;
g3opts = defg3opts;
if (!tiffcp(in, out) || !TIFFWriteDirectory(out))
goto bad;
} while (TIFFReadDirectory(in));
(void) TIFFClose(in);
}
}
(void) TIFFClose(out);
exit(0);
bad:
unlink(TIFFFileName(out));
exit(1);
}
static
CheckAndCorrectColormap(n, r, g, b)
int n;
u_short *r, *g, *b;
{
int i;
for (i = 0; i < n; i++)
if (r[i] >= 256 || g[i] >= 256 || b[i] >= 256)
return;
TIFFWarning(filename, "Scaling 8-bit colormap");
#define CVT(x) (((x) * ((1L<<16)-1)) / 255)
for (i = 0; i < n; i++) {
r[i] = CVT(r[i]);
g[i] = CVT(g[i]);
b[i] = CVT(b[i]);
}
#undef CVT
}
static struct cpTag {
long tag;
short count;
TIFFDataType type;
} tags[] = {
{ TIFFTAG_SUBFILETYPE, 1, TIFF_LONG },
{ TIFFTAG_PHOTOMETRIC, 1, TIFF_SHORT },
{ TIFFTAG_THRESHHOLDING, 1, TIFF_SHORT },
{ TIFFTAG_DOCUMENTNAME, 1, TIFF_ASCII },
{ TIFFTAG_IMAGEDESCRIPTION, 1, TIFF_ASCII },
{ TIFFTAG_MAKE, 1, TIFF_ASCII },
{ TIFFTAG_MODEL, 1, TIFF_ASCII },
{ TIFFTAG_ORIENTATION, 1, TIFF_SHORT },
{ TIFFTAG_MINSAMPLEVALUE, 1, TIFF_SHORT },
{ TIFFTAG_MAXSAMPLEVALUE, 1, TIFF_SHORT },
{ TIFFTAG_XRESOLUTION, 1, TIFF_RATIONAL },
{ TIFFTAG_YRESOLUTION, 1, TIFF_RATIONAL },
{ TIFFTAG_PAGENAME, 1, TIFF_ASCII },
{ TIFFTAG_XPOSITION, 1, TIFF_RATIONAL },
{ TIFFTAG_YPOSITION, 1, TIFF_RATIONAL },
{ TIFFTAG_GROUP4OPTIONS, 1, TIFF_LONG },
{ TIFFTAG_RESOLUTIONUNIT, 1, TIFF_SHORT },
{ TIFFTAG_PAGENUMBER, 2, TIFF_SHORT },
{ TIFFTAG_SOFTWARE, 1, TIFF_ASCII },
{ TIFFTAG_DATETIME, 1, TIFF_ASCII },
{ TIFFTAG_ARTIST, 1, TIFF_ASCII },
{ TIFFTAG_HOSTCOMPUTER, 1, TIFF_ASCII },
{ TIFFTAG_WHITEPOINT, 1, TIFF_RATIONAL },
{ TIFFTAG_PRIMARYCHROMATICITIES,-1,TIFF_RATIONAL },
{ TIFFTAG_HALFTONEHINTS, 2, TIFF_SHORT },
{ TIFFTAG_BADFAXLINES, 1, TIFF_LONG },
{ TIFFTAG_CLEANFAXDATA, 1, TIFF_SHORT },
{ TIFFTAG_CONSECUTIVEBADFAXLINES,1, TIFF_LONG },
{ TIFFTAG_INKSET, 1, TIFF_SHORT },
{ TIFFTAG_INKNAMES, 1, TIFF_ASCII },
{ TIFFTAG_DOTRANGE, 2, TIFF_SHORT },
{ TIFFTAG_TARGETPRINTER, 1, TIFF_ASCII },
{ TIFFTAG_SAMPLEFORMAT, 1, TIFF_SHORT },
{ TIFFTAG_YCBCRCOEFFICIENTS, -1,TIFF_RATIONAL },
{ TIFFTAG_YCBCRSUBSAMPLING, 2, TIFF_SHORT },
{ TIFFTAG_YCBCRPOSITIONING, 1, TIFF_SHORT },
{ TIFFTAG_REFERENCEBLACKWHITE, -1,TIFF_RATIONAL },
{ TIFFTAG_MATTEING, 1, TIFF_SHORT },
};
#define NTAGS (sizeof (tags) / sizeof (tags[0]))
static void
cpOtherTags(in, out)
TIFF *in, *out;
{
struct cpTag *p;
short shortv, shortv2;
float floatv, *floatav;
char *stringv;
u_long longv;
for (p = tags; p < &tags[NTAGS]; p++)
switch (p->type) {
case TIFF_SHORT:
if (p->count == 1) {
CopyField(p->tag, shortv);
} else if (p->count == 2) {
CopyField2(p->tag, shortv, shortv2);
}
break;
case TIFF_LONG:
CopyField(p->tag, longv);
break;
case TIFF_RATIONAL:
if (p->count == 1) {
CopyField(p->tag, floatv);
} else if (p->count == -1) {
CopyField(p->tag, floatav);
}
break;
case TIFF_ASCII:
CopyField(p->tag, stringv);
break;
}
}
static int
tiffcp(in, out)
TIFF *in, *out;
{
short bitspersample, samplesperpixel, shortv, bystrip;
u_long w, l;
CopyField(TIFFTAG_IMAGEWIDTH, w);
CopyField(TIFFTAG_IMAGELENGTH, l);
CopyField(TIFFTAG_BITSPERSAMPLE, bitspersample);
if (compression != (u_short)-1)
TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
else
CopyField(TIFFTAG_COMPRESSION, compression);
if (fillorder != 0)
TIFFSetField(out, TIFFTAG_FILLORDER, fillorder);
else
CopyField(TIFFTAG_FILLORDER, shortv);
CopyField(TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
if (rowsperstrip < 0) {
/*
* RowsPerStrip is left unspecified: use either the
* value from the input image or, if nothing is defined,
* something that approximates 8Kbyte strips.
*/
if (!TIFFGetField(in, TIFFTAG_ROWSPERSTRIP, &rowsperstrip))
rowsperstrip = (8*1024)/TIFFScanlineSize(out);
}
if (rowsperstrip == 0)
rowsperstrip = 1L;
TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
if (config != -1)
TIFFSetField(out, TIFFTAG_PLANARCONFIG, config);
else
CopyField(TIFFTAG_PLANARCONFIG, config);
if (g3opts != 0)
TIFFSetField(out, TIFFTAG_GROUP3OPTIONS, g3opts);
else
CopyField(TIFFTAG_GROUP3OPTIONS, g3opts);
if (samplesperpixel <= 4) {
u_short *tr, *tg, *tb, *ta;
CopyField4(TIFFTAG_TRANSFERFUNCTION, tr, tg, tb, ta);
}
if (predictor != 0)
TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
else
CopyField(TIFFTAG_PREDICTOR, predictor);
{ u_short *red, *green, *blue;
if (TIFFGetField(in, TIFFTAG_COLORMAP, &red, &green, &blue)) {
CheckAndCorrectColormap(1<<bitspersample, red, green, blue);
TIFFSetField(out, TIFFTAG_COLORMAP, red, green, blue);
}
}
/* TileWidth & TileLength */
/* SMinSampleValue & SMaxSampleValue */
/* JPEG stuff */
cpOtherTags(in, out);
(void) TIFFGetField(in, TIFFTAG_PLANARCONFIG, &shortv);
if (shortv != config && bitspersample != 8 && samplesperpixel > 1) {
fprintf(stderr,
"Can't handle different planar configuration w/ bits/sample != 8\n");
return (0);
}
{ long irps = -1L;
TIFFGetField(in, TIFFTAG_ROWSPERSTRIP, &irps);
bystrip = (rowsperstrip == irps);
}
#define pack(a,b,c) ((u_long)(((a)<<9)|((b)<<1)|(c)))
switch (pack(shortv, config, bystrip)) {
case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_CONTIG, 0):
return (cpContig2ContigByRow(in, out, l));
case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_CONTIG, 1):
return (cpDecodedStrips(in, out, l));
case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, 0):
case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, 1):
return (cpSeparate2SeparateByRow(in, out, l, samplesperpixel));
case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_SEPARATE, 0):
case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_SEPARATE, 1):
return (cpContig2SeparateByRow(in, out, l, samplesperpixel, w));
case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG, 0):
case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG, 1):
return (cpSeparate2ContigByRow(in, out, l, samplesperpixel, w));
default:
fprintf(stderr,
"tiffcp: %s: Unknown planar configuration (in=%d out=%d).\n",
TIFFFileName(in), shortv, config);
return (0);
}
/*NOTREACHED*/
}
static int
cpContig2ContigByRow(in, out, imagelength)
TIFF *in, *out;
u_long imagelength;
{
u_char *buf = (u_char *)malloc(TIFFScanlineSize(in));
u_long row;
for (row = 0; row < imagelength; row++) {
if (TIFFReadScanline(in, buf, row, 0) < 0 && !ignore)
goto done;
if (TIFFWriteScanline(out, buf, row, 0) < 0)
goto bad;
}
done:
free(buf);
return (1);
bad:
free(buf);
return (0);
}
static int
cpDecodedStrips(in, out, h)
TIFF *in, *out;
u_long h;
{
u_long stripsize = TIFFStripSize(in);
u_char *buf = (u_char *)malloc(stripsize);
if (buf) {
u_int s, ns = TIFFNumberOfStrips(in);
u_long row = 0;
for (s = 0; s < ns; s++) {
u_int cc = (row + rowsperstrip > h) ?
TIFFVStripSize(in, h - row) : stripsize;
if (TIFFReadEncodedStrip(in, s, buf, cc) < 0 && !ignore)
break;
if (TIFFWriteEncodedStrip(out, s, buf, cc) < 0) {
free(buf);
return (0);
}
row += rowsperstrip;
}
free(buf);
return (1);
}
return (0);
}
static int
cpSeparate2SeparateByRow(in, out, imagelength, samplesperpixel)
TIFF *in, *out;
u_long imagelength;
short samplesperpixel;
{
u_char *buf = (u_char *)malloc(TIFFScanlineSize(in));
u_long row;
int s;
for (s = 0; s < samplesperpixel; s++) {
for (row = 0; row < imagelength; row++) {
if (TIFFReadScanline(in, buf, row, s) < 0 && !ignore)
goto done;
if (TIFFWriteScanline(out, buf, row, s) < 0)
goto bad;
}
}
done:
free(buf);
return (1);
bad:
free(buf);
return (0);
}
static int
cpContig2SeparateByRow(in, out, imagelength, samplesperpixel, imagewidth)
TIFF *in, *out;
u_long imagelength;
short samplesperpixel;
u_long imagewidth;
{
u_char *inbuf = (u_char *)malloc(TIFFScanlineSize(in));
u_char *outbuf = (u_char *)malloc(TIFFScanlineSize(out));
register u_char *inp, *outp;
register u_long n;
u_long row;
int s;
/* unpack channels */
for (s = 0; s < samplesperpixel; s++) {
for (row = 0; row < imagelength; row++) {
if (TIFFReadScanline(in, inbuf, row, 0) < 0 && !ignore)
goto done;
inp = inbuf + s;
outp = outbuf;
for (n = imagewidth; n-- > 0;) {
*outp++ = *inp;
inp += samplesperpixel;
}
if (TIFFWriteScanline(out, outbuf, row, s) < 0)
goto bad;
}
}
done:
if (inbuf) free(inbuf);
if (outbuf) free(outbuf);
return (1);
bad:
if (inbuf) free(inbuf);
if (outbuf) free(outbuf);
return (0);
}
static int
cpSeparate2ContigByRow(in, out, imagelength, samplesperpixel, imagewidth)
TIFF *in, *out;
u_long imagelength;
int samplesperpixel;
u_long imagewidth;
{
u_char *inbuf = (u_char *)malloc(TIFFScanlineSize(in));
u_char *outbuf = (u_char *)malloc(TIFFScanlineSize(out));
register u_char *inp, *outp;
register u_long n;
u_long row;
int s;
for (row = 0; row < imagelength; row++) {
/* merge channels */
for (s = 0; s < samplesperpixel; s++) {
if (TIFFReadScanline(in, inbuf, row, s) < 0 && !ignore)
goto done;
inp = inbuf;
outp = outbuf + s;
for (n = imagewidth; n-- > 0;) {
*outp = *inp++;
outp += samplesperpixel;
}
}
if (TIFFWriteScanline(out, outbuf, row, 0) < 0)
goto bad;
}
done:
if (inbuf) free(inbuf);
if (outbuf) free(outbuf);
return (1);
bad:
if (inbuf) free(inbuf);
if (outbuf) free(outbuf);
return (0);
}
static void
usage()
{
fprintf(stderr, "usage: tiffcp [options] input... output\n");
fprintf(stderr, "where options are:\n");
fprintf(stderr,
" -contig\tpack samples contiguously (e.g. RGBRGB...)\n");
fprintf(stderr,
" -separate\tstore samples separately (e.g. RRR...GGG...BBB...)\n");
fprintf(stderr, "\n");
fprintf(stderr, " -lsb2msb\tforce lsb-to-msb FillOrder for output\n");
fprintf(stderr, " -msb2lsb\tforce msb-to-lsb FillOrder for output\n");
fprintf(stderr, "\n");
fprintf(stderr,
" -lzw\t\tcompress output with Lempel-Ziv & Welch encoding\n");
fprintf(stderr,
" -packbits\tcompress output with packbits encoding\n");
fprintf(stderr,
" -g3\t\tcompress output with CCITT Group 3 encoding\n");
fprintf(stderr,
" -g4\t\tcompress output with CCITT Group 4 encoding\n");
fprintf(stderr,
" -none\t\tuse no compression algorithm on output\n");
fprintf(stderr, "\n");
fprintf(stderr,
" -2d\t\tuse 2d encoding when compressing with Group 3\n");
fprintf(stderr,
" -fill\t\tzero-fill scanlines when compressing with Group 3\n");
fprintf(stderr, "\n");
fprintf(stderr,
" -rowsperstrip #\tmake each strip have no more than # rows\n");
fprintf(stderr, " -predictor\tset LZW predictor value\n");
fprintf(stderr, " -ignore\tignore read errors\n");
exit(-1);
}